//Author: Max Charnock
//Date: 16/02/2015
//Purpose: Class that takes a function pointer and excutes it when told. has two different textures or colours to indicate when
//selected.

#pragma once

#include "../nclgl/OBJMesh.h"
#include "Renderer.h"

//forward declaration for function pointers
class HUDManager;

using namespace std;

template <class T>
class Button
{
protected:

	//whether the button has a texture
	bool textured;

	//whether button is selected
	bool selected;

	//texture path for when not selected
	GLuint StandardTex;
	//texture path for when selected
	GLuint SelectedTex;

	//scene node for button
	SceneNode button;

	//function pointer
	void (T::*p_function)(void);

public:

	//contructor takes position of button size of button and function to run when triggered
	Button(Vector3 position,float size,void (T::*function)(void));
	~Button();

	//runs function pointer
	void Execute();

	//sets Textures
	void SetTextures(string standardtex,string selectedtex);

	//toggles selected bool, gets selected bool
	void ToggleSelected();
	bool GetSelected() { return selected; }
	
	//returns pointer to scene node
	SceneNode* GetSceneNode() {return &button;}

	


};

/////////////////////////////defination cause of templates///////////////////////////////

template <class T>
Button<T>::Button(Vector3 position, float size, void (T::*function)(void))
{
	//set bools
	textured = false;
	selected = false;

	//create scene node
	button.SetMesh(Mesh::GenerateQuad());
	button.SetColour(Vector4(1, 1, 1, 1));
	button.SetModelScale(Vector3(size * 4, size, 1));
	button.SetTransform(Matrix4::Translation(position));

	//set function pointer
	p_function = function;
}

template <class T>
Button<T>::~Button()
{
}

template <class T>
void Button<T>::Execute()
{
	//run function pointer
	if (p_function)
	{
		//weird syntax for running a function pointer to a singleton
		(T::GetInstance()->*(this->p_function))();
	}
}

template <class T>
//sets Textures
void Button<T>::SetTextures(string standardtex, string selectedtex)
{
	//loads textures and sets them to GLUINTs
	StandardTex = (SOIL_load_OGL_texture(selectedtex.c_str(), SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS));
	SelectedTex = (SOIL_load_OGL_texture(standardtex.c_str(), SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS));

	//sets textured to be true
	textured = true;

	//resets button colour
	button.SetColour(Vector4(1, 1, 1, 1));

	//sets mesh texture dependant on whether its selected
	if (selected)
	{
		button.GetMesh()->SetTexture(StandardTex);
	}
	else
	{
		button.GetMesh()->SetTexture(SelectedTex);
	}


}

template <class T>
void Button<T>::ToggleSelected()
{

	selected = !selected;

	if (textured)
	{
		if (selected)
		{
			button.GetMesh()->SetTexture(StandardTex);


		}
		else
		{
			button.GetMesh()->SetTexture(SelectedTex);

		}
	}
	else
	{
		if (selected)
		{
			button.SetColour(Vector4(0, 255, 0, 1));
		}
		else
		{
			button.SetColour(Vector4(1, 1, 1, 1));
		}
	}

}
